package org.budo.warehouse.service.bean;

import javax.annotation.Resource;
import javax.sql.DataSource;

import org.budo.druid.util.DruidUtil;
import org.budo.support.lang.util.StringUtil;
import org.budo.support.spring.bean.factory.support.BeanBuilder;
import org.budo.support.spring.util.SpringUtil;
import org.budo.warehouse.service.api.ServiceDynamicBeanProvider;
import org.budo.warehouse.service.entity.DataNode;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Component;

import com.alibaba.druid.pool.DruidDataSource;

import lombok.extern.slf4j.Slf4j;

/**
 * @author limingwei
 */
@Slf4j
@Component
public class ServiceDynamicBeanProviderImpl implements ServiceDynamicBeanProvider {
    @Resource
    private ApplicationContext applicationContext;

    @Override
    public DataSource dataSource(DataNode dataNode, String schema) {
        String url = dataNode.getUrl();

        if (!StringUtil.startWith(url, "jdbc:")) {
            log.error("#33 return null dataSource, not jdbc, dataNode=" + dataNode);
            return null;
        }

        // 直达
        String beanId = "DataSource-" + dataNode.getId() + "-" + url + "-" + schema + "-" + dataNode.getUsername();
        DruidDataSource dataSource = (DruidDataSource) SpringUtil.getBeanCached(this.applicationContext, beanId);
        if (null != dataSource && !dataSource.isClosed() && dataSource.isEnable()) {
            return dataSource;
        }

        // 初始化
        String password = DruidUtil.rsaDecrypt(dataNode.getPassword());
        DruidDataSource druidDataSource = (DruidDataSource) new BeanBuilder() //
                .id(beanId) //
                .parent("abstractDruidDataSource") //
                .propertyValue("url", url) //
                .propertyValue("username", dataNode.getUsername()) //
                .propertyValue("password", password) //
                .initMethod("init") // initMethod
                .registerTo(this.applicationContext) //
                .get();

        if (null != druidDataSource && !druidDataSource.isClosed() && druidDataSource.isEnable()) {
            return druidDataSource;
        }

        throw new RuntimeException("#60 druidDataSource=" + druidDataSource);
    }

    @Override
    public DataSource dataSource(DataNode dataNode) {
        return this.dataSource(dataNode, null);
    }
}